
// import oimo.m.Mat3;
// import oimo.m.Quat;
// import oimo.m.Vec3;
// import oimo.m.M;
// import oimo.common.Mat3;
// import oimo.common.Quat;
import { Vec3 } from "./Vec3";
import { Mat3 } from "./Mat3";
import { Quat } from "./Quat";

/**
 * Transform class provides a set of translation and rotation.
 */
export class Transform {
	_position: Vec3;
	_rotation: Mat3;

	/**
	 * Creates a new identical transform.
	 */
	constructor(pos?: Vec3, rot?: Mat3) {
		this._position = pos ? pos.clone() : new Vec3();
		this._rotation = rot ? rot.clone() : new Mat3();
	}

	/**
	 * Sets the transformation to identity and returns `this`.
	 */
	public identity(): Transform {
		this._position = new Vec3();
		this._rotation = new Mat3();
		return this;
	}

	/**
	 * Returns the position of the transformation.
	 */
	public getPosition(): Vec3 {
		// TODO: 这里有clone
		return this._position.clone();
	}

	/**
	 * Sets `position` to the position of the transformation.
	 *
	 * This does not create a new instance of `Vec3`.
	 */
	public getPositionTo(position: Vec3): void {
		position.copyFrom(this._position);
	}

	/**
	 * Sets the position of the transformation to `position` and returns `this`.
	 */
	public setPosition(position: Vec3): Transform {
		this._position.copyFrom(position);
		return this;
	}

	/**
	 * Translates the position by `translation`.
	 */
	public translate(translation: Vec3): void {
		this._position.add(translation);
	}

	/**
	 * Returns the rotation matrix.
	 */
	public getRotation(): Mat3 {
		// TODO: 这里有clone
		return this._rotation.clone();
	}

	/**
	 * Sets `out` to the rotation matrix.
	 *
	 * This does not create a new instance of `Mat3`.
	 */
	public getRotationTo(out: Mat3): void {
		out.copyFrom(this._rotation);
	}

	/**
	 * Sets the rotation matrix to `rotation` and returns `this`.
	 */
	public setRotation(rotation: Mat3): Transform {
		this._rotation.copyFrom(rotation);
		return this;
	}

	/**
	 * Sets the rotation by Euler angles `eulerAngles` in radians.
	 */
	public setRotationXyz(eulerAngles: Vec3): void {
		this._rotation.fromEulerXyz(eulerAngles);
	}

	/**
	 * Applies rotation by the rotation matrix `rotation`.
	 */
	public rotate(rotation: Mat3): void {
		this._rotation = rotation.mul(this._rotation);
	}

	/**
	 * Applies the rotation by Euler angles `eulerAngles` in radians.
	 */
	public rotateXyz(eulerAngles: Vec3): void {
		let rot = new Mat3();
		rot.fromEulerXyz(eulerAngles);
		this._rotation = rot.mul(this._rotation);
	}

	/**
	 * Returns the rotation as a quaternion.
	 */
	public getOrientation(): Quat {
		var q: Quat = new Quat();
		q.fromMat3(this._rotation);
		return q;
	}

	/**
	 * Sets `orientation` to the quaternion representing the rotation.
	 *
	 * This does not create a new instance of `Quat`.
	 */
	public getOrientationTo(orientation: Quat): void {
		orientation.fromMat3(this._rotation);
	}

	/**
	 * Sets the rotation from a quaternion `quaternion` and returns `this`.
	 */
	public setOrientation(quaternion: Quat): Transform {
		this._rotation.fromQuat(quaternion);
		return this;
	}

	/**
	 * Returns a clone of the transformation.
	 */
	public clone(): Transform {
		var tf = new Transform();
		tf._position.copyFrom(this._position);
		tf._rotation.copyFrom(this._rotation);
		return tf;
	}

	/**
	 * Sets the transformation to `transform` and returns `this`.
	 */
	public copyFrom(transform: Transform): Transform {
		this._position.copyFrom(transform._position);
		this._rotation.copyFrom(transform._rotation);
		return this;
	}

}

